package com.nc.delivery_project.server.dao;

import com.nc.delivery_project.server.domain.User;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by miroshnik on 11.02.2015.
 */
public abstract class PersonDao<T extends User> extends AbstractDao<T> {

    public static final String SELECT_BY_USER_ID = "select_by_user_id";
    protected static final String PERSON_ID = "person_id";
    protected static final String USER_ID = "user_id";

    public PersonDao(String entityName) {
        super(entityName);
    }

    public PersonDao(Connection connection) throws SQLException {
        super(connection);
    }

    public PersonDao(Connection connection, String entityName) throws SQLException {
        super(connection, entityName);
    }

    @Override
    protected void prepareInsertStatement(CallableStatement statement, T object) throws SQLException {

        statement.setString(2, object.getEmail());
        statement.registerOutParameter(3, Types.NUMERIC);

        doPrepareInsertStatement(statement, object);
    }

    @Override
    protected void prepareUpdateStatement(CallableStatement statement, T object) throws SQLException {
        statement.setString(1, object.getEmail());
        statement.setInt(2, object.getId());

        doPrepareUpdateStatement(statement, object);
    }

    @Override
    protected List<T> parseResultSet(ResultSet rs) throws SQLException {
        List<T> users = new ArrayList<>();

        while (rs.next()) {
            users.add(parsePerson(rs));
        }

        return users;
    }

    @Override
    public int create(T obj) throws SQLException {
        return super.create(obj, 3);
    }

    public T readByUserId(int id) throws SQLException {
        String query = queryManager.getQuery(entityName, SELECT_BY_USER_ID);
        try (PreparedStatement statement = connection.prepareStatement(query)) {
            statement.setInt(1, id);
            ResultSet rs = statement.executeQuery();
            List<T> result = parseResultSet(rs);
            return result.size() > 0 ? result.get(0) : null;
        }
    }

    protected abstract void doPrepareInsertStatement (CallableStatement statement, T object) throws SQLException;

    protected abstract void doPrepareUpdateStatement (CallableStatement statement, T object) throws SQLException;

    protected abstract T parsePerson(ResultSet rs) throws SQLException;
}
